﻿using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using Resn.WhuPub.BIL;
using Resn.WhuPub.DAL;
using Resn.WhuPub.DML;
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.IO;
using System.Linq;

namespace Resn.WhuPub.BLL
{
        /// <summary>
        /// 实现学校/公司管理器的属性和方法
        /// </summary>
        public class CorporateManager : ICorporateManager
        {


                #region 属性

                private static CorporateManager _instance;

                /// <summary>
                /// 获取学校/公司管理器实例
                /// </summary>
                /// <value>
                /// 学校/公司管理器实例
                /// </value>
                public static CorporateManager Instance
                {
                        get { return _instance ?? (_instance = new CorporateManager()); }
                }

                /// <summary>
                /// 获取所有学校/公司集合
                /// </summary>
                /// <returns>
                /// 所有学校/公司集合
                /// </returns>
                public List<ICorporate> Corporates
                {
                        get
                        {
                                var models = DBStorage.Instance.Select<CorporateModel>();

                                var corporates = new List<ICorporate>();

                                models.ForEach(i => corporates.Add(new Corporate(i)));

                                return corporates;
                        }
                }

                private List<ICorporateBranch> _corporateBranchs; 

                public List<ICorporateBranch> CorporateBranchs
                {
                        get
                        {
                                if (_corporateBranchs == null)
                                {
                                        _corporateBranchs = new List<ICorporateBranch>();

                                        var models = DBStorage.Instance.Select<CorporateBranchModel>();

                                        models.ForEach(i => _corporateBranchs.Add(new CorporateBranch(i)));
                                }

                                return _corporateBranchs;
                        }
                }

                #endregion 属性

                #region 方法

                /// <summary>
                /// 创建学校/公司
                /// </summary>
                /// <param name="name">名称</param>
                /// <param name="corporateLevel">层次</param>
                /// <returns>
                /// 成功返回创建的对象，失败返回NULL
                /// </returns>
                /// <exception cref="System.InvalidOperationException">该名称学校/公司已存在</exception>
                public ICorporate CreateCorporate(String name, CorporateLevel corporateLevel)
                {
                        Contract.Requires(!string.IsNullOrEmpty(name), "学校/公司名称不能为空");

                        if (DBCheck.ExistName(Corporates, name))
                        {
                                throw new InvalidOperationException("该名称学校/公司已存在");
                        }

                        var model = new CorporateModel
                        {
                                Id = Guid.NewGuid().ToString(),
                                Name = name,
                                CorporateLevel = corporateLevel.ToString()
                        };

                        return new Corporate(model);
                }

                

                #endregion 方法

                /// <summary>
                /// 从EXCEL文件加载学校集合
                /// </summary>
                /// <param name="path">EXCEL文件路径</param>
                /// <returns>
                /// 学校集合
                /// </returns>
                /// <exception cref="System.InvalidOperationException">文件不存在，无法加载</exception>
                public Dictionary<ICorporate, List<ICorporateBranch>> LoadCorporatesFromExcel(string path)
                {
                        if (!File.Exists(path))
                        {
                                throw new InvalidOperationException("文件不存在，无法加载");
                        }

                        var result = new Dictionary<ICorporate, List<ICorporateBranch>>();

                        using (var fileStream = new FileStream(path, FileMode.Open))
                        {
                                var workBook = new HSSFWorkbook(fileStream);
                                var sheet = workBook.GetSheetAt(0);

                                var rowsCount = sheet.PhysicalNumberOfRows;
                                var columnsCount = sheet.GetRow(0).PhysicalNumberOfCells;

                                if (columnsCount < 8)
                                {
                                        throw new InvalidOperationException("列错误，无法导入");
                                }

                                if (rowsCount < 2)
                                {
                                        throw new InvalidOperationException("行错误，无法导入");
                                }

                                IRow row;
                                string corporateName;
                                string corporateBranchName;
                                string province;
                                string city;
                                string address;
                                string Postcode;
                                string webSite;
                                string corporateLevel;

                                for (int i = 1; i < rowsCount; i++)
                                {
                                        row = sheet.GetRow(i);

                                        corporateName = row.Cells[0].StringCellValue;
                                        corporateBranchName = row.Cells[1].StringCellValue;
                                        province = row.Cells[2].StringCellValue;
                                        city = row.Cells[3].StringCellValue;
                                        address = row.Cells[4].StringCellValue;
                                        Postcode = row.Cells[5].StringCellValue;
                                        webSite = row.Cells[6].StringCellValue;
                                        corporateLevel = row.Cells[7].StringCellValue;

                                        CorporateLevel level;
                                        bool success = Enum.TryParse(corporateLevel, out level);
                                        if (!success)
                                        {
                                                throw new InvalidOperationException(i + "行学校层次错误，无法导入");
                                        }

                                        ICorporate corporate;
                                        if (result.Keys.Any(j => j.Name == corporateName))
                                        {
                                                corporate = result.Keys.Single(k => k.Name == corporateName);
                                        }
                                        else
                                        {
                                                corporate = CreateCorporate(corporateName, level);
                                                result.Add(corporate, new List<ICorporateBranch>());
                                        }

                                        if (string.IsNullOrEmpty(corporateBranchName))
                                        {
                                                corporateBranchName = "本部";
                                        }

                                        if (result[corporate].Any(k => k.Name == corporateBranchName))
                                        {
                                                throw new InvalidOperationException(i + "行分校名称错误，无法导入");
                                        }

                                        var corporateBranch = corporate.CreateCorporateBranch(corporateBranchName, address, Postcode, province,
                                                                        city, webSite);

                                        result[corporate].Add(corporateBranch);
                                }
                        }

                        return result;
                }
        }
}